package com.link.base.base.mpconfig.service;

import com.alibaba.fastjson.JSONObject;
import com.link.base.base.mpconfig.dao.mybatis.mapper.MpTemplateMapper;
import com.link.base.base.mpconfig.model.*;
import com.link.base.base.sms.model.MsgResult;
import com.link.base.base.sms.model.PushSms;
import com.link.base.base.sms.service.MsgResultService;
import com.link.base.base.sms.service.PushSmsService;
import com.link.base.sms.model.Template;
import com.link.base.wechat.basic.util.WxExceptionUtil;
import com.link.base.wechat.wxmessage.util.WxMsgUtil;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.util.*;
import com.link.core.util.redisclient.LinkRedisClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 小程序模板消息
 *
 * @author: 闫有霞
 * @date: 2019/12/19
 */
@Service
public class MpTemplateServiceImpl extends BasicServiceImpl<Template> implements MpTemplateService {

    private static final Logger logger = LogManager.getLogger(MpTemplateServiceImpl.class);
    /*获取小程序账号的类目url*/
    private String getCategoryUrl = "https://api.weixin.qq.com/wxaapi/newtmpl/getcategory?access_token=ACCESS_TOKEN";
    /*获取帐号所属类目下的公共模板标题url*/
    private String getPubTemplateTitleListUrl = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles?access_token=ACCESS_TOKEN";
    /*获取模板标题下的关键词列表*/
    private String getPubTemplateKeyWordUrl = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords?access_token=ACCESS_TOKEN";
    /*获取当前帐号下的个人模板列表*/
    private String getTemplateListUrl = "https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token=ACCESS_TOKEN";
    /*发送订阅消息url*/
    public static final String SEND_SUB_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN";

    @Resource
    private MpTemplateMapper mpTemplateMapper;

    @Resource
    private MpService mpService;

    @Resource
    private MpTokenService mpTokenService;

    @Resource
    private PushSmsService pushSmsService;

    @Resource
    private MsgResultService msgResultService;

    @Resource
    private SendTempMessageService sendTempMessageService;

    @Override
    public BasicMapper<Template> getBasicMapper() {
        return mpTemplateMapper;
    }

    @Override
    public List<Mp> getMpCategory(String accesstoken) throws Exception {
        String reqUrl = getCategoryUrl.replace("ACCESS_TOKEN",accesstoken);
        String resultStr = HttpRequestUtil.sendGet(reqUrl, null);
        JSONObject json = WxExceptionUtil.parse(resultStr);
        List<Mp> mpList = new ArrayList<>();
        // 正确码为0
        if (json != null && StringUtils.equals(json.get("errcode").toString(),"0")) {
            mpList = JSONObject.parseArray(json.get("data").toString(),Mp.class);
        }
        return mpList;
    }

    @Override
    public List<PubTemplateTitle> getPubTemplateTitleList(String accesstoken) throws Exception {
        // 获取类目信息
        List<Mp> mpList = this.getMpCategory(accesstoken);
        int size = mpList.size();
        if (size == 0) {
            throw new BasicServiceException("BUS-MPMSG-07");
        }
        // 获取类目id用“，”逗号隔开
        String ids = "";
        for (int i = 0 ; i < size ; i++) {
            if (i < size - 1) {
                ids = ids + mpList.get(i).getId() + ",";
            } else {
                ids = ids + mpList.get(i).getId();
            }
        }
        // 查询公共模板标题
        Map<String,Object> dataMap = queryubTempTitleList(ids,accesstoken,0);
        // 模板数量
        int count = 0;
        List<PubTemplateTitle> titles = new ArrayList<>();
        count = Integer.parseInt(dataMap.get("count").toString());
        titles = (List<PubTemplateTitle>)dataMap.get("titles");
        if (count <= 30) {
            return titles;
        } else {
            // 分页查询，汇总返回
            // 取除数
            int num = count / 30;
            // 取余数
            int yushu = count % 30;
            if (yushu > 0) {
                num += 1;
            }
            List<PubTemplateTitle> titleList = new ArrayList<>();
            titleList.addAll(titles);
            for (int i = 1;i < num;i++) {
                // 查询公共模板标题
                Map<String,Object> data = queryubTempTitleList(ids,accesstoken,i);
                // 重新赋值
                titles = (List<PubTemplateTitle>)data.get("titles");
                // 汇总
                titleList.addAll(titles);
            }
            return titleList;
        }
    }

    /**
     * 查询公共模板标题
     *
     * @author 路江
     * @date 2020-1-6
     * @param ids 类目id
     * @param accesstoken 全局唯一凭证
     * @return
     * @throws Exception
     */
    private Map<String,Object> queryubTempTitleList(String ids,String accesstoken,int num) throws Exception {
        int start = num * 30;
        // 请求参数
        String param = "ids=" + ids + "&&start=" + start + "&&limit=" + 30;
        String reqUrl = getPubTemplateTitleListUrl.replace("ACCESS_TOKEN", accesstoken) + "&" + param;
        String resultStr = HttpRequestUtil.sendGet(reqUrl, null);
        JSONObject json = WxExceptionUtil.parse(resultStr);
        List<PubTemplateTitle> titles = new ArrayList<>();
        int count = 0;
        if (json != null && StringUtils.equals(json.get("errcode").toString(),"0")) {
            //先获取数量，再考虑分页的问题
            count = Integer.parseInt(json.get("count").toString());
            titles = JSONObject.parseArray(json.get("data").toString(),PubTemplateTitle.class);
        }
        Map<String,Object> map = new HashMap<>();
        map.put("count",count);
        map.put("titles",titles);
        return map;
    }


    @Override
    public List<PubTemplateKeyWord> getPubTemplateKeyWordsById(PubTemplateTitle entity,String accesstoken) throws Exception {
        // 为空校验
        if (entity == null || StringUtils.isBlank(entity.getTid())) {
            throw new BasicServiceException("BUS-MPMSG-06");
        }
        String param = "tid=" + entity.getTid();
        String reqUrl = getPubTemplateKeyWordUrl.replace("ACCESS_TOKEN", accesstoken) + "&" + param;
        String resultStr = HttpRequestUtil.sendGet(reqUrl, null);
        JSONObject json = WxExceptionUtil.parse(resultStr);
        List<PubTemplateKeyWord> keyWords = new ArrayList<>();
        if (json != null && StringUtils.equals(json.get("errcode").toString(),"0")) {
            //先获取数量，再考虑分页的问题
            keyWords = JSONObject.parseArray(json.get("data").toString(),PubTemplateKeyWord.class);
        }
        return keyWords;
    }

    /**
     * 截取字符串str中指定字符 strStart、strEnd之间的字符串
     *
     * @author 路江
     * @date 2020-1-7
     * @param str 字符串
     * @param strStart 开始字符串
     * @param strEnd 结束字符串
     * @return
     */
    public static String subString(String str, String strStart, String strEnd) {
        /* 找出指定的2个字符在 该字符串里面的 位置 */
        int strStartIndex = str.indexOf(strStart);
        int strEndIndex = str.indexOf(strEnd);
        /* index 为负数 即表示该字符串中 没有该字符 */
        if (strStartIndex < 0) {
            return "字符串 :---->" + str + "<---- 中不存在 " + strStart + ", 无法截取目标字符串";
        }
        if (strEndIndex < 0) {
            return "字符串 :---->" + str + "<---- 中不存在 " + strEnd + ", 无法截取目标字符串";
        }
        /* 开始截取 */
        String result = str.substring(strStartIndex, strEndIndex).substring(strStart.length());
        return result;
    }

    @Override
    public JSONObject getTemplateList(Mp entity) throws Exception {
        // 查询到appid
        entity = mpService.queryById(entity);
        // 获取小程序唯一凭证
        String accesstoken = mpTokenService.getMpAccessToken(entity);
        String reqUrl = getTemplateListUrl.replace("ACCESS_TOKEN", accesstoken);
        String resultStr = HttpRequestUtil.sendGet(reqUrl, null);
        JSONObject json = WxExceptionUtil.parse(resultStr);
        return json;
    }

    @Override
    public Map<String, Object> subscribeMessageSend(SendTempMessage entity) throws Exception {
        Map<String, Object> map = new HashMap<>();
        logger.info("开始发送订阅消息");
        // 获取小程序信息
        Mp mp = new Mp();
        mp.setAppId(entity.getAppId());
        mp = mpService.queryMpInfoByAppId(mp);
        // 获取全局唯一凭证
        String accesstoken = mpTokenService.getMpAccessToken(mp);
        // 将列表排序
        JSONObject jsonObject = this.getTemplateList(mp);
        List<MpDyTemplate> dyTemplates = jsonObject.getJSONArray("data").toJavaList(MpDyTemplate.class);
        String content = null;
        for (MpDyTemplate template : dyTemplates) {
            if (StringUtils.equals(template.getPriTmplId(),entity.getTemplateId())) {
                content = template.getContent();
            }
        }
        if (content == null) {
            return map;
        }
        String[] stringList = content.split("\n");
        // 最后得到的顺序
        List<String> list = new ArrayList<>();
        for (int i = 0;i < stringList.length;i++) {
            list.add(subString(stringList[i],"{{","."));
        }
        // 获取发送消息体
        Map<String, Object> key = new HashMap<>();
        for (int i = 0 ;i < list.size();i++) {
            Map<String, Object> value = new HashMap<>();
            if (list.get(i).contains("date")) {
                value.put("value",DateUtil.dateToStr(DateUtil.stringToDate(entity.getParams().get(i),DateUtil.DATE_TIME),DateUtil.DATE_TIME));
            } else {
                value.put("value",entity.getParams().get(i));
            }
            key.put(list.get(i),value);
        }
        entity.setData(key);
        MsgResult msgResult = new MsgResult();
        msgResult.setSceneId(entity.getPushSceneId());
        msgResult.setSendType("Immediately");
        msgResult.setMsgType("MiniProgram");
        msgResult.setSendTime(DateUtil.dateToStr(new Date(),DateUtil.DATE_TIME));
        msgResult.setOpenId(entity.getOpenId());
        Map<String, Object> result = new HashMap<>(16);
        map.put("touser",entity.getOpenId());
        map.put("template_id",entity.getTemplateId());
        if (StringUtils.isNotBlank(entity.getPageUrl())) {
            map.put("page",entity.getPageUrl());
        }
        map.put("data",entity.getData());
        // 数据json字符串
        String msgJson = JsonUtil.toString(map);
        msgResult.setContent(msgJson);
        try {
            // 发送小程序订阅消息
            map.put("code",WxMsgUtil.subscribeMessageSend(accesstoken,entity));
            msgResult.setStatus("Succeeded");
        } catch (Exception e) {
            msgResult.setStatus("Failed");
            msgResult.setErrMsg(e.toString());
        }
        msgResultService.insert(msgResult);
        return map;
    }

    /**
     * 订阅消息模块-- 通过模板消息标题查询模板标题id
     *
     * @author lujiang
     * @date 2019-11-26
     * @return
     * @throws Exception
     */
    private String queryMpTid(Mp mp,String accessToken,String title) throws Exception {
        LinkRedisClient jedis = null;
        String tid = null;
        try {
            jedis = RedisUtil.getJedis();
            tid = jedis.hget(title,mp.getAppId());
            if (StringUtils.isBlank(tid)) {
                // 从新去获取一遍模板标题
                List<PubTemplateTitle> list = getPubTemplateTitleList(accessToken);
                for (PubTemplateTitle pubTemplateTitle : list) {
                    if (StringUtils.isBlank(jedis.hget(pubTemplateTitle.getTitle(),mp.getAppId()))) {
                        jedis.hset(pubTemplateTitle.getTitle(),mp.getAppId(),pubTemplateTitle.getTid());
                    }
                }
                tid = jedis.hget(title,mp.getAppId());
            }
        } catch (Exception e) {
            e.getMessage();
        } finally {
            RedisUtil.returnResource(jedis);
        }
        return tid;
    }

    /**
     * 发送小程序订阅消息
     *
     * @author 路江
     * @date 2019/11/18 11:52
     */
    public void sendMpSubscribeMsg(SendTempMessage entity) throws Exception {
        // 获取小程序订阅模板记录id
        logger.info("小程序订阅消息入参：" + entity.toString());
        PushSms pushSms = pushSmsService.queryPushSmsByType(entity.getType());
        SendTempMessage params = new SendTempMessage();
        /**判断该场景下小程序模板发送是否启用*/
        /**开关打开标志*/
        String open = "Y";
        if (open.equals(pushSms.getMpOpenFlag())) {
            /**获取模板ID*/
            params.setTempRowId(pushSms.getMpTempId());
            params.setType("MP");
            params.setParentId(entity.getId());
            /**获取data参数及page跳转页面参数*/
            SendTempMessage sendTempMessage = sendTempMessageService.getParamsTest(params);
            /**获取发送小程序模板的参数*/
            sendTempMessage.setMpTempTitle(pushSms.getMpTempTitle());
            sendTempMessage.setAppId(entity.getAppId());
            sendTempMessage.setOpenId(entity.getOpenId());
            sendTempMessage.setPushSceneId(pushSms.getId());
            // 发送订阅消息
            subscribeMessageSend(sendTempMessage);
        }
    }
}

